package drds.plus.sql_process.type;

import drds.plus.sql_process.abstract_syntax_tree.expression.NullValue;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.optimizer.OptimizerException;
import drds.tools.ShouldNeverHappenException;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;

public class Types {

    public static Type getTypeOfObject(Object o) {
        if (o == null || o instanceof NullValue) {
            return Type.NullType;
        }
        Class clazz = o.getClass();
        if (clazz == Integer.class || clazz == int.class) {
            return Type.IntegerType;
        }
        if (clazz == Long.class || clazz == long.class) {
            return Type.LongType;
        }
        if (clazz == Short.class || clazz == short.class) {
            return Type.ShortType;
        }
        if (clazz == Float.class || clazz == float.class) {
            return Type.FloatType;
        }
        if (clazz == Double.class || clazz == double.class) {
            return Type.DoubleType;
        }
        if (clazz == Byte.class || clazz == byte.class) {
            return Type.ByteType;
        }
        if (clazz == Boolean.class || clazz == boolean.class) {
            return Type.BooleanType;
        }
        if (clazz == BigInteger.class) {
            return Type.BigIntegerType;
        }
        if (clazz == BigDecimal.class) {
            return Type.BigDecimalType;
        }

        if (clazz == Timestamp.class || clazz == java.util.Date.class || Calendar.class.isAssignableFrom(clazz)) {
            return Type.TimestampType;
        }
        if (clazz == java.sql.Date.class) {
            return Type.DateType;
        }
        if (clazz == Time.class) {
            return Type.TimeType;
        }

        if (clazz == Byte[].class || clazz == byte[].class || Blob.class.isAssignableFrom(clazz)) {
            //return Type.BytesType;
            throw new ShouldNeverHappenException();
        }

        if (clazz == String.class || Clob.class.isAssignableFrom(clazz)) {
            return Type.StringType;
        }

        if (o instanceof Item) {
            return ((Item) o).getType();
        }

        throw new OptimizerException("type: " + o.getClass().getSimpleName() + " is not supported");
    }


    /**
     * 判断是否为时间类型
     */
    public static boolean isDateType(Type type) {
        return type != null && (type == Type.DateType || type == Type.TimeType || type == Type.TimestampType || type == Type.DatetimeType || type == Type.YearType);
    }

}
